package com.huajin.codetest.designpattern;

/**
 * 
 * https://zhuanlan.zhihu.com/p/160835278
 * https://blog.csdn.net/qq_41458550/article/details/109243456
 * https://zhuanlan.zhihu.com/p/162894749
 * 
 * 单例模式
 * 1、构造函数设置为 private ，这避免外部通过 new 创建实例
 * 2、通过一个静态方法或者枚举返回单例类对象
 * 3、考虑对象创建时的线程安全问题，确保单例类的对象有且仅有一个，尤其是在多线程环境下
 * 4、确保单例类对象在反序列化时不会重新构建对象
 * 5、考虑是否支持延迟加载（Lazy Loading）
 */
public class Singleton {
	
	private Singleton() {}
	
	 /**
	  * 饿汉式（静态常量）
	  * 1、线程安全
	  * 2、不支持延迟加载
	  * 3、可用
	  */
	private static final Singleton instance1 = new Singleton();
	 
	public static Singleton getInstance1() {
		return instance1;
	}
	
	 /**
	  * 饿汉式（静态代码快）
	  * 1、线程安全
	  * 2、不支持延迟加载
	  * 3、可用
	  */
	private static Singleton instance11;
	
	static {
		instance11 = new Singleton();
	}
	 
	public static Singleton getInstance11() {
		return instance11;
	}
	
	/**
	 * 懒汉式（线程安全）
	 * 1、支持延迟加载
	 * 2、并发性能低
	 * 3、不推荐使用
	 */
	private static Singleton instance2;
	
	public static synchronized Singleton getInstance2() {
        if (instance2 == null) {
        	instance2 = new Singleton();
        }
        return instance2;
    }
	
	/**
	 * 懒汉式（线程不安全）
	 * 1、支持延迟加载
	 * 2、线程不安全
	 * 3、不可用
	 */
	private static Singleton instance22;
	
	public static Singleton getInstance22() {
        if (instance22 == null) {
        	instance22 = new Singleton();
        }
        return instance22;
    }
	
	/**
	 * 懒汉式（线程不安全）
	 * 1、支持延迟加载
	 * 2、线程不安全
	 * 3、不可用
	 * 4、实现就有问题
	 */
	private static Singleton instance23;
	
	public static Singleton getInstance23() {
        if (instance23 == null) {
        	synchronized (Singleton.class) {
        		instance23 = new Singleton();
			}
        }
        return instance23;
    }
	
	/**
	 * 双重检测
	 * 1、支持延迟加载
	 * 2、资源利用率高
	 * 3、第一次加载慢
	 * 4、低版本有问题，高版本推荐使用
	 */
	private static Singleton instance3;
	
    public static Singleton getInstance3() {
        if (instance3 == null) {
            synchronized (Singleton.class) {
                if (instance3 == null) {
                	//-- 低版本不是原子操作，可能指令重排，高版本则线程安全？？？怎么证明
                	instance3 = new Singleton();
                }
            }
        }
        return instance2;
    }
    
    /**
     * 双重检测变种
     * 解决方案
     * 1、给instance成员变量加上volatile关键字，禁止指令重排序
     * 2、高版本Java对象new操作和初始化操作设计为原子操作，自然能禁止指令重排序？？？怎么证明
     * 3、推荐使用
     */
    private static volatile Singleton instance4;
	
    public static Singleton getInstance4() {
        if (instance4 == null) {
            synchronized (Singleton.class) {
                if (instance4 == null) {
                	instance4 = new Singleton();
                }
            }
        }
        return instance4;
    }
    
    /**
     * 静态内部类
     * 1、线程安全
     * 2、支持延迟加载
     * 3、效率高
     * 4、推荐使用
     */
    private static class Instance5 {
        private static final Singleton instance5 = new Singleton();
    } 

    public static Singleton getInstance5() {
        return Instance5.instance5;
    }
    
    /**
     * 枚举
     * 1、线程安全
     * 2、推荐使用
     */
    public enum Singleton6 {
    	
        INSTANCE6;
    	
    	public void self() {}
    	
    }

}

